package com.enation.app.javashop.core.trade.order.service.impl;

import com.enation.app.javashop.core.aftersale.service.AfterSaleManager;
import com.enation.app.javashop.core.promotion.fulldiscount.model.dos.FullDiscountGiftDO;
import com.enation.app.javashop.core.trade.TradeErrorCode;
import com.enation.app.javashop.core.trade.cart.model.vo.CouponVO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderDO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderItemsDO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderMetaDO;
import com.enation.app.javashop.core.trade.order.model.dto.OrderDetailQueryParam;
import com.enation.app.javashop.core.trade.order.model.dto.OrderQueryParam;
import com.enation.app.javashop.core.trade.order.model.enums.*;
import com.enation.app.javashop.core.trade.order.model.vo.*;
import com.enation.app.javashop.core.trade.order.service.OrderMetaManager;
import com.enation.app.javashop.core.trade.order.service.OrderQueryManager;
import com.enation.app.javashop.core.trade.sdk.model.OrderDetailDTO;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.database.Page;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.util.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 订单查询业务实现类
 *
 * @author Snow create in 2018/5/14
 * @version v2.0
 * @since v7.0.0
 */
@Service
public class OrderQueryManagerImpl implements OrderQueryManager {

    @Autowired
    @Qualifier("tradeDaoSupport")
    private DaoSupport daoSupport;

    @Autowired
    private AfterSaleManager afterSaleManager;

    @Autowired
    private OrderMetaManager orderMetaManager;


    @Override
    public Page list(OrderQueryParam paramDTO) {

        StringBuffer sql = new StringBuffer("select * from es_order o where disabled=0 ");
        List<Object> term = new ArrayList<>();

        if(paramDTO.getKeywords()!=null){
            sql.append(" and (sn like ? or items_json like ? )");
            term.add("%"+paramDTO.getKeywords()+"%");
            term.add("%"+paramDTO.getKeywords()+"%");
        }

        // 按卖家查询
        Integer sellerId = paramDTO.getSellerId();
        if (sellerId != null) {
            sql.append(" and o.seller_id=?");
            term.add(sellerId);
        }

        // 按买家查询
        Integer memberId = paramDTO.getMemberId();
        if (memberId != null) {
            sql.append(" and o.member_id=?");
            term.add(memberId);
        }

        // 按订单编号查询
        if (StringUtil.notEmpty(paramDTO.getOrderSn())) {
            sql.append(" and o.sn like ?");
            term.add("%"+paramDTO.getOrderSn()+"%");
        }

        // 按交易编号查询
        if (StringUtil.notEmpty(paramDTO.getTradeSn())) {
            sql.append(" and o.trade_sn like ?");
            term.add("%"+paramDTO.getTradeSn()+"%");
        }

        // 按时间查询
        Long startTime = paramDTO.getStartTime();
        Long endTime = paramDTO.getEndTime();
        if (startTime != null) {

            String startDay = DateUtil.toString(startTime, "yyyy-MM-dd");
            sql.append(" and o.create_time >= ?");
            term.add(DateUtil.getDateline(startDay + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));
        }

        if (endTime != null) {
            String endDay = DateUtil.toString(endTime, "yyyy-MM-dd");
            sql.append(" and o.create_time <= ?");
            term.add(DateUtil.getDateline(endDay + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));
        }

        // 按购买人用户名
        String memberName = paramDTO.getBuyerName();
        if (StringUtil.notEmpty(memberName)) {
            sql.append(" and o.member_name like ?");
            term.add("%"+memberName+"%");
        }

        // 按标签查询
        String tag = paramDTO.getTag();
        if (!StringUtil.isEmpty(tag)) {
            OrderTagEnum tagEnum = OrderTagEnum.valueOf(tag);
            switch (tagEnum) {
                case ALL:
                    break;
                //待付款
                case WAIT_PAY:
                    // 非货到付款的，未付款状态的可以结算 OR 货到付款的要发货或收货后才能结算
                    sql.append(" and ( ( payment_type!='cod' and  order_status='" + OrderStatusEnum.CONFIRM + "') ");
                    sql.append(" or ( payment_type='cod' and   order_status='" + OrderStatusEnum.ROG + "'  ) )");
                    break;

                //待发货
                case WAIT_SHIP:
                    // 非货到付款的，要已结算才能发货 OR 货到付款的，已确认就可以发货
                    sql.append(" and( ( payment_type!='cod'  and  order_status='" + OrderStatusEnum.PAID_OFF + "')  ");
                    sql.append(" or ( payment_type='cod' and  order_status='" + OrderStatusEnum.CONFIRM + "')) ");
                    break;

                //待收货
                case WAIT_ROG:
                    sql.append(" and o.order_status='" + OrderStatusEnum.SHIPPED + "'");
                    break;

                //待评论
                case WAIT_COMMENT:
                    sql.append(" and o.ship_status='" + ShipStatusEnum.SHIP_ROG + "' and o.comment_status='" + CommentStatusEnum.UNFINISHED + "' ");
                    break;

                //已取消
                case CANCELLED:
                    sql.append(" and o.order_status='" + OrderStatusEnum.CANCELLED + "'");
                    break;

                case COMPLETE:
                    sql.append(" and o.order_status='" + OrderStatusEnum.COMPLETE + "'");
                    break;
                default:
                    break;
            }
        }
        //订单状态
        if (!StringUtil.isEmpty(paramDTO.getOrderStatus())) {
            sql.append(" and o.order_status = ?");
            term.add(paramDTO.getOrderStatus());
        }

        if (StringUtil.notEmpty(paramDTO.getBuyerName())) {
            sql.append(" and o.items_json like ?");
            term.add("%" + paramDTO.getGoodsName() + "%");
        }
        if (StringUtil.notEmpty(paramDTO.getShipName())) {
            sql.append(" and o.ship_name like ?");
            term.add("%" + paramDTO.getShipName() + "%");
        }
        // 按商品名称查询
        if (StringUtil.notEmpty(paramDTO.getGoodsName())) {
            sql.append(" and o.items_json like ?");
            term.add("%" + paramDTO.getGoodsName() + "%");
        }

        sql.append(" order by o.order_id desc");

        // 先按PO进行查询
        Page<OrderDO> page = daoSupport.queryForPage(sql.toString(), paramDTO.getPageNo(), paramDTO.getPageSize(),
                OrderDO.class, term.toArray());

        // 转为VO
        List<OrderDO> orderList = page.getData();
        List<OrderLineVO> lineList = new ArrayList();
        for (OrderDO orderDO : orderList) {
            OrderLineVO line = new OrderLineVO(orderDO);
            lineList.add(line);
        }


        // 生成新的Page
        long totalCount = page.getDataTotal();
        Page<OrderLineVO> linePage = new Page(paramDTO.getPageNo(), totalCount, paramDTO.getPageSize(), lineList);

        return linePage;
    }


    @Override
    public OrderDetailVO getModel(String orderSn,OrderDetailQueryParam queryParam) {

        List param = new ArrayList();

        StringBuffer sql = new StringBuffer();
        sql.append("select * from es_order where sn = ? ");
        param.add(orderSn);

        if (queryParam !=null && queryParam.getSellerId() != null) {
            sql.append(" and seller_id =?");
            param.add(queryParam.getSellerId());

        } else if (queryParam !=null && queryParam.getBuyerId() != null) {
            sql.append(" and member_id=? ");
            param.add(queryParam.getBuyerId());
        }

        OrderDO orderDO = this.daoSupport.queryForObject(sql.toString(), OrderDO.class, param.toArray());
        if (orderDO == null) {
            throw new ServiceException(TradeErrorCode.E453.code(), "订单不存在");
        }

        OrderDetailVO detailVO = new OrderDetailVO();
        BeanUtils.copyProperties(orderDO, detailVO);
        //初始化sku信息
        List<OrderSkuVO> skuList = JsonUtil.jsonToList(orderDO.getItemsJson(), OrderSkuVO.class);
        for (OrderSkuVO skuVO : skuList) {
            //设置商品的可操作状态
            skuVO.setGoodsOperateAllowableVO(new GoodsOperateAllowable(PaymentTypeEnum.valueOf(orderDO.getPaymentType()), OrderStatusEnum.valueOf(orderDO.getOrderStatus()),
                    ShipStatusEnum.valueOf(orderDO.getShipStatus()), ServiceStatusEnum.valueOf(skuVO.getServiceStatus()),
                    PayStatusEnum.valueOf(orderDO.getPayStatus())));
        }
        detailVO.setOrderSkuList(skuList);

        // 初始化订单允许状态
        OrderOperateAllowable operateAllowableVO = new OrderOperateAllowable(PaymentTypeEnum.valueOf(orderDO.getPaymentType()),
                OrderStatusEnum.valueOf(orderDO.getOrderStatus()), CommentStatusEnum.valueOf(orderDO.getCommentStatus()),
                ShipStatusEnum.valueOf(orderDO.getShipStatus()), ServiceStatusEnum.valueOf(orderDO.getServiceStatus()),
                PayStatusEnum.valueOf(orderDO.getPayStatus()));
        detailVO.setOrderOperateAllowableVO(operateAllowableVO);


       List<OrderMetaDO> metalList  =  this.orderMetaManager.list(orderSn);


        for (OrderMetaDO metaDO : metalList) {

            //订单的赠品信息
            if (OrderMetaKeyEnum.GIFT.name().equals(metaDO.getMetaKey())) {
                String giftJson =  metaDO.getMetaValue();
                if(!StringUtil.isEmpty(giftJson)) {
                    List<FullDiscountGiftDO> giftList = JsonUtil.jsonToList(giftJson, FullDiscountGiftDO.class);
                    detailVO.setGiftList(giftList);
                }
            }

            //使用的积分
            if (OrderMetaKeyEnum.POINT.name().equals(metaDO.getMetaKey())) {
                String pointStr  =  metaDO.getMetaValue();
                int point =0;
                if(!StringUtil.isEmpty(pointStr)){
                    point =  Integer.valueOf(pointStr);
                }

                detailVO.setUsePoint(point);

            }


            //赠送的积分
            if (OrderMetaKeyEnum.GIFT_POINT.name().equals(metaDO.getMetaKey())) {
                String giftPointStr  =  metaDO.getMetaValue();
                int giftPoint =0;
                if(!StringUtil.isEmpty(giftPointStr)){
                    giftPoint =  Integer.valueOf(giftPoint);
                }

                detailVO.setGiftPoint(giftPoint);

            }


            //满减金额
            if (OrderMetaKeyEnum.FULL_MINUS.name().equals(metaDO.getMetaKey())) {
                Double fullMinus = 0D;
                if(!StringUtil.isEmpty(metaDO.getMetaValue())){
                    fullMinus =  Double.valueOf(metaDO.getMetaValue());
                }
                detailVO.setFullMinus(fullMinus);
            }


            if ( OrderMetaKeyEnum.COUPON.name().equals(metaDO.getMetaKey()) ){

                String couponJson =  metaDO.getMetaValue();
                if(!StringUtil.isEmpty(couponJson)) {
                    List<CouponVO> couponList = JsonUtil.jsonToList(couponJson, CouponVO.class);
                    if(couponList!=null && !couponList.isEmpty()){
                        CouponVO couponVO = couponList.get(0);
                        detailVO.setGiftCoupon(couponVO);
                    }

                }

            }

            //优惠卷抵扣金额
            if (OrderMetaKeyEnum.COUPON_PRICE.name().equals(metaDO.getMetaKey())) {
                String couponPriceStr  =  metaDO.getMetaValue();
                Double couponPrice =0D;
                if(!StringUtil.isEmpty(couponPriceStr)){
                    couponPrice =  Double.valueOf(couponPriceStr);
                }
                //设置优惠卷抵扣金额
                detailVO.setCouponPrice(couponPrice);

            }



        }


        //查询订单优惠卷抵扣金额
        String couponPriceStr  = this.orderMetaManager.getMetaValue(orderSn, OrderMetaKeyEnum.COUPON_PRICE);
        Double couponPrice =0D;

        if(!StringUtil.isEmpty(couponPriceStr)){
            couponPrice =  Double.valueOf(couponPriceStr);
        }

        //设置优惠卷抵扣金额
        detailVO.setCouponPrice(couponPrice);

        //设置订单的返现金额
        Double cashBack =CurrencyUtil.sub(detailVO.getDiscountPrice(), couponPrice);
        detailVO.setCashBack(cashBack);

        return detailVO;
    }




    @Override
    public OrderStatusNumVO getOrderStatusNum(Integer memberId, Integer sellerId) {

        StringBuffer sql = new StringBuffer("select order_status,pay_status,ship_status,payment_type,comment_status,count(order_id) as count from es_order o ");

        List<Object> term = new ArrayList<>();

        List<String> sqlSplice = new ArrayList<>();
        //按商家查询
        if (sellerId != null) {
            sqlSplice.add("o.seller_id = ? ");
            term.add(sellerId);
        }
        // 按买家查询
        if (memberId != null) {
            sqlSplice.add("o.member_id = ? ");
            term.add(memberId);
        }
        String sqlSplicing = SqlSplicingUtil.sqlSplicing(sqlSplice);
        if (!StringUtil.isEmpty(sqlSplicing)) {
            sql.append(sqlSplicing);
        }
        sql.append(" GROUP BY order_status,pay_status,ship_status,comment_status,payment_type ");

        List<Map<String, Object>> list = this.daoSupport.queryForList(sql.toString(), term.toArray());

        // 所有订单数
        StringBuilder allNumSql = new StringBuilder("select count(order_id) as count from es_order o ");
        if (!StringUtil.isEmpty(sqlSplicing)) {
            allNumSql.append(sqlSplicing);
        }

        OrderStatusNumVO numVO = new OrderStatusNumVO();
        numVO.setWaitShipNum(0);
        numVO.setWaitPayNum(0);
        numVO.setWaitRogNum(0);
        numVO.setCompleteNum(0);
        numVO.setCancelNum(0);
        numVO.setWaitCommentNum(0);
        numVO.setAllNum(this.daoSupport.queryForInt(allNumSql.toString(), term.toArray()));

        // 支付状态未支付，订单状态已确认，为待付款订单
        for (Map map : list) {
            boolean flag  = (OrderStatusEnum.CONFIRM.value().equals(map.get("order_status").toString()) && !"COD".equals(map.get("payment_type").toString()))
                    || (OrderStatusEnum.ROG.value().equals(map.get("order_status").toString()) && "COD".equals(map.get("payment_type").toString()));
            if (flag) {
                numVO.setWaitPayNum(numVO.getWaitPayNum()+(null == map.get("count") ? 0 : Integer.parseInt(map.get("count").toString())));
            }

            // 物流状态为未发货，订单状态为已收款，为待发货订单
            flag  = (OrderStatusEnum.CONFIRM.value().equals(map.get("order_status").toString()) && "COD".equals(map.get("payment_type").toString()))
                    || (OrderStatusEnum.PAID_OFF.value().equals(map.get("order_status").toString()) && !"COD".equals(map.get("payment_type").toString()));
            if ( flag  ) {
                numVO.setWaitShipNum(numVO.getWaitShipNum()+(null == map.get("count") ? 0 : Integer.parseInt(map.get("count").toString())));
            }

            // 订单状态为已发货，为待收货订单
            if (OrderStatusEnum.SHIPPED.value().equals(map.get("order_status").toString())) {
                numVO.setWaitRogNum(numVO.getWaitRogNum()+(null == map.get("count") ? 0 : Integer.parseInt(map.get("count").toString())));
            }

            // 订单状态为已取消，为已取消订单
            if (OrderStatusEnum.CANCELLED.value().equals(map.get("order_status").toString())) {
                numVO.setCancelNum(numVO.getCancelNum()+(null == map.get("count") ? 0 : Integer.parseInt(map.get("count").toString())));
            }

            // 订单状态为已完成，为已完成订单
            if (OrderStatusEnum.COMPLETE.value().equals(map.get("order_status").toString())) {
                numVO.setCompleteNum(numVO.getCompleteNum()+(null == map.get("count") ? 0 : Integer.parseInt(map.get("count").toString())));
            }

            // 评论状态为未评论，订单状态为已收货，为待评论订单
            if (CommentStatusEnum.UNFINISHED.value().equals(map.get("comment_status").toString()) && OrderStatusEnum.ROG.value().equals(map.get("order_status").toString())) {
                numVO.setWaitCommentNum(numVO.getWaitCommentNum()+(null == map.get("count") ? 0 : Integer.parseInt(map.get("count").toString())));
            }
        }

        // 申请售后，但未完成售后的订单
        numVO.setRefundNum(this.afterSaleManager.getAfterSaleCount(memberId, sellerId));

        return numVO;

    }

    @Override
    public List<OrderFlow> getOrderFlow(String orderSn) {

        OrderDetailVO orderDetailVO = this.getModel(orderSn,null);
        String orderStatus = orderDetailVO.getOrderStatus();
        String paymentType = orderDetailVO.getPaymentType();

        //新订单
        OrderFlow orderCreateFlow = new OrderFlow(OrderStatusEnum.NEW);
        //订单确认
        OrderFlow orderConfirmFlow = new OrderFlow(OrderStatusEnum.CONFIRM);
        //订单已付款
        OrderFlow orderPaidOffFlow = new OrderFlow(OrderStatusEnum.PAID_OFF);
        //已发货
        OrderFlow orderShippedFlow = new OrderFlow(OrderStatusEnum.SHIPPED);
        //已收货
        OrderFlow orderRogFlow = new OrderFlow(OrderStatusEnum.ROG);
        //已完成
        OrderFlow orderCompleteFlow = new OrderFlow(OrderStatusEnum.COMPLETE);
        //售后中
        OrderFlow orderAfteserviceFlow = new OrderFlow(OrderStatusEnum.AFTER_SERVICE);
        //已取消
        OrderFlow orderCancelledFlow = new OrderFlow(OrderStatusEnum.CANCELLED);

        List<OrderFlow> resultFlow = new ArrayList<>();
        resultFlow.add(orderCreateFlow);
        resultFlow.add(orderConfirmFlow);
        //订单取消
        if (OrderStatusEnum.CANCELLED.value().equals(orderStatus)) {
            resultFlow.add(orderCancelledFlow);

            //货到付款
        } else if (PaymentTypeEnum.COD.value().equals(paymentType)) {
            resultFlow.add(orderShippedFlow);
            resultFlow.add(orderRogFlow);
            resultFlow.add(orderPaidOffFlow);
            resultFlow.add(orderCompleteFlow);
        } else {//款到发货
            resultFlow.add(orderPaidOffFlow);
            resultFlow.add(orderShippedFlow);
            resultFlow.add(orderRogFlow);
            resultFlow.add(orderCompleteFlow);
        }
        boolean flowFinish = true;
        int i = 1;

        //0:灰色,1:普通显示,2:结束显示,3:取消显示
        for (OrderFlow flow : resultFlow) {

            if (flowFinish) {
                if (flow.getOrderStatus().equals(OrderStatusEnum.CANCELLED.value())) {
                    flow.setShowStatus(3);
                } else {
                    if (i == resultFlow.size()) {
                        flow.setShowStatus(2);
                    } else {
                        flow.setShowStatus(1);
                    }
                }
            }
            i++;
            if (flow.getOrderStatus().equals(orderStatus)) {
                flowFinish = false;
                break;
            }
        }
        return resultFlow;
    }


    @Override
    public Integer getOrderNumByMemberId(Integer memberId) {
        String sql = "select count(0) from es_order where member_id=?";
        Integer num = this.daoSupport.queryForInt(sql, memberId);
        return num;
    }


    @Override
    public Integer getOrderCommentNumByMemberId(Integer memberId,String commentStatus) {
        StringBuffer sql = new StringBuffer("select count(0) from es_order where member_id=? ") ;

        sql.append(" and ship_status='" + ShipStatusEnum.SHIP_ROG +"' and comment_status = ?  ");

        Integer num = this.daoSupport.queryForInt(sql.toString(),memberId,commentStatus);
        return num;
    }


    @Override
    public List<OrderDetailDTO> getOrderByTradeSn(String tradeSn) {
        List<OrderDetailVO> orderDetailVOList = this.getOrderByTradeSn(tradeSn, null);

        List<OrderDetailDTO> orderDetailDTOList = new ArrayList<>();
        for (OrderDetailVO orderDetailVO : orderDetailVOList) {
            OrderDetailDTO orderDetailDTO = new OrderDetailDTO();
            BeanUtils.copyProperties(orderDetailVO, orderDetailDTO);
            orderDetailDTOList.add(orderDetailDTO);
        }
        return orderDetailDTOList;
    }

    @Override
    public List<OrderDetailVO> getOrderByTradeSn(String tradeSn, Integer memberId) {
        String sql = "select * from es_order where trade_sn = ?";
        List<OrderDetailVO> orderDetailVOList = this.daoSupport.queryForList(sql, OrderDetailVO.class, tradeSn);

        if (orderDetailVOList == null) {
            return new ArrayList<>();
        }
        return orderDetailVOList;
    }

    @Override
    public List<OrderItemsDO> orderItems(String orderSn) {
        return daoSupport.queryForList("select * from es_order_items where order_sn = ?", OrderItemsDO.class, orderSn);
    }

    @Override
    public Page getReceiptHistory(Integer sellerId, Integer pageNo, Integer pageSize) {
        StringBuffer sqlBuffer = new StringBuffer("select * from es_order where need_receipt = 'yes'");
        List<Object> term = new ArrayList<>();
        if (sellerId != null) {
            sqlBuffer.append(" and seller_id = ?");
            term.add(sellerId);
        }
        sqlBuffer.append(" order by order_id desc");
        Page page = this.daoSupport.queryForPage(sqlBuffer.toString(), pageNo, pageSize, OrderDO.class, term.toArray());
        List<ReceiptHistoryVO> receiptHistoryVOList = new ArrayList<>();
        List<OrderDO> orderDOList = page.getData();
        for (OrderDO orderDO : orderDOList) {
            ReceiptHistoryVO receiptHistoryVO = new ReceiptHistoryVO();
            receiptHistoryVO.setMemberId(orderDO.getMemberId());
            receiptHistoryVO.setCreateTime(orderDO.getCreateTime());
            receiptHistoryVO.setMemberName(orderDO.getMemberName());
            receiptHistoryVO.setNeedPayMoney(orderDO.getNeedPayMoney());
            receiptHistoryVO.setSn(orderDO.getSn());
            receiptHistoryVOList.add(receiptHistoryVO);
        }
        page.setData(receiptHistoryVOList);
        return page;
    }
}
